package com.cctc.juc.source.Bitc.Icontainer.hash;

import java.util.*;

/**
 * [HashTable（过渡）线程安全的哈希表]
 * 要求：熟练掌握（手撕、陈述）HashTable [（过渡）线程安全的哈希表] 核心（主干）实现逻辑。
 * 概述：HashTable 是 JDK（1.0）第一版就提供的一个线程安全的容器，其内部是一个由 Entry 数组构建的哈希表，底层实现原理与 HashMap 几乎一样，通过在包含 put/get 在内的所有需要并发执行的方法上加上 synchronized 关键字，来解决哈希表的线程安全问题。
 * - 缺点：HashTable 为了解决线程安全问题，相当于给整个哈希表加了一把大锁，即所有的同步方法公用同一把 Java 内置锁。当一个线程访问 HashTable 的任何一个同步方法时，其他所有线程都会被阻塞，相当于将所有的操作串行化执行，效率非常低下。
 */
public class BHTable_AAAAA<K, V> extends Dictionary<K, V> implements Map<K, V> {
    /**
     * [Entry 数据节点（数据模型）] 内部类。
     * - 单向链表，只有 next 后继节点。
     */
    private static class Entry<K, V> implements Map.Entry<K, V> {
        final int hash;
        final K key;
        V value;
        Entry<K, V> next;

        public Entry(int hash, K key, V value, Entry<K, V> next) {
            this.hash = hash;
            this.key = key;
            this.value = value;
            this.next = next;
        }

        @Override
        public K getKey() {
            return key;
        }

        @Override
        public V getValue() {
            return value;
        }

        @Override
        public V setValue(V newValue) {
            if (newValue == null) throw new NullPointerException();
            V oldValue = this.value;
            this.value = newValue;
            return oldValue;
        }

        @Override
        public String toString() {
            return key + "=" + value;
        }

        @Override
        public int hashCode() {
            return Objects.hashCode(key) ^ Objects.hashCode(value);
        }

        @Override
        public boolean equals(Object obj) {
            if (obj == this) return true;
            if (obj instanceof Map.Entry) {
                Map.Entry entry = (Map.Entry) obj;
                if (entry.getKey().equals(key) && entry.getValue().equals(value)) {
                    return true;
                }
            }
            return false;
        }
    }

    private transient Entry<K, V>[] table;
    private transient int size;
    private float loadFactor;
    private int threshold;
    private transient int modCount;

    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

    // --- [核心构造器] --- //

    public BHTable_AAAAA(int initialCapacity, float loadFactor) {
        if (initialCapacity < 0) throw new IllegalArgumentException();
        if (loadFactor <= 0 || Float.isNaN(loadFactor)) throw new IllegalArgumentException();
        if (initialCapacity == 0) initialCapacity = 1;
        this.loadFactor = loadFactor;
        this.table = new Entry[initialCapacity];
        this.threshold = (int) Math.min(initialCapacity * loadFactor, MAX_ARRAY_SIZE + 1);
    }

    // --- [核心方法] --- //

    @Override
    public synchronized V put(K key, V value) {
        if (value == null) throw new NullPointerException();
        Entry<?, ?>[] tab = table;
        int hash = key.hashCode();
        int index = (hash & 0x7FFFFFFF) % tab.length;
        Entry<K, V> cur = (Entry<K, V>) tab[index];
        for (; cur != null; cur = cur.next) {
            if ((cur.hash == hash) && cur.key.equals(key)) {
                V oldValue = cur.value;
                cur.value = value;
                return oldValue;
            }
        }
        return null;
    }

    @Override
    public synchronized V get(Object key) {
        Entry<?, ?>[] tab = table;
        int hash = key.hashCode();
        int index = (hash & 0x7FFFFFFF) % tab.length;
        for (Entry<?, ?> cur = tab[index]; cur != null; cur = cur.next) {
            if ((cur.hash == hash) && cur.key.equals(key)) {
                return (V) cur.value;
            }
        }
        return null;
    }

    @Override
    public synchronized V remove(Object key) {
        Entry<?, ?>[] tab = table;
        int hash = key.hashCode();
        int index = (hash & 0x7FFFFFFF) % tab.length;
        Entry<K, V> cur = (Entry<K, V>) tab[index];
        for (Entry<K, V> prev = null; cur != null; prev = cur, cur = cur.next) {
            if ((cur.hash == hash) && cur.key.equals(key)) {
                if (prev != null) prev.next = cur.next;
                else tab[index] = cur.next;
                modCount++;
                size--;
                V oldValue = cur.value;
                cur.value = null;
                return oldValue;
            }
        }
        return null;
    }

    @Override
    public synchronized int size() {
        return size;
    }

    @Override
    public synchronized void clear() {
        Entry<?, ?>[] tab = table;
        for (int index = tab.length; --index >= 0; ) {
            tab[index] = null;
        }
        modCount++;
        size = 0;
    }

    // --- [其他方法] --- //

    @Override
    public boolean isEmpty() {
        return false;
    }

    @Override
    public boolean containsKey(Object key) {
        return false;
    }

    @Override
    public boolean containsValue(Object value) {
        return false;
    }

    @Override
    public Enumeration<K> keys() {
        return null;
    }

    @Override
    public Enumeration<V> elements() {
        return null;
    }

    @Override
    public void putAll(Map<? extends K, ? extends V> m) {

    }

    @Override
    public Set<K> keySet() {
        return null;
    }

    @Override
    public Collection<V> values() {
        return null;
    }

    @Override
    public Set<Map.Entry<K, V>> entrySet() {
        return null;
    }

}
